`include"defines.v"
`include"csr_defines.v"

module csr_regfile(

    input  wire            clk,
	input  wire            rst,

    input  wire [11:0]     csr_addr,
    input  wire            csr_rd_ena,
    input  wire            csr_wr_ena, 
    input  wire [63:0]     csr_wr_data,

    output reg  [63:0]     csr_rd_data,

    output reg  [63:0]     mstatus_o,
    output reg  [63:0]     mie_o,
    output reg  [63:0]     mepc_o,
    output reg  [63:0]     mcause_o,
    output reg  [63:0]     mtval_o,
    output reg  [63:0]     mip_o,
     
    output reg  [63:0]     mcycle_o,
    output reg  [63:0]     minstret_o
    
    
);
//csr machine
    reg [63:0] csr_mstatus;
    reg [63:0] csr_mie;
    reg [63:0] csr_mepc;
    reg [63:0] csr_mcause;
    reg [63:0] csr_mtval;
    reg [63:0] csr_mip;
//csr user 
    reg [63:0] csr_mcycle;
    reg [63:0] csr_minstret;


    always @(posedge clk) 
	begin
		if ( rst == `RST ) 
		begin
            csr_mstatus     <=    `ZERO_WORD;
            csr_mie         <=    `ZERO_WORD;
            csr_mepc        <=    `ZERO_WORD;
            csr_mcause      <=    `ZERO_WORD;
            csr_mtval       <=    `ZERO_WORD;
            csr_mip         <=    `ZERO_WORD;
            csr_mcycle      <=    `ZERO_WORD;
            csr_minstret    <=    `ZERO_WORD;
        end
        else if (csr_wr_ena)
            begin	
                case (csr_addr) 
                    `MSTATUS  : csr_mstatus   <=   csr_wr_data;
                    `MIE      : csr_mie       <=   csr_wr_data;
                    `MEPC     : csr_mepc      <=   csr_wr_data;
                    `MCAUSE   : csr_mcause    <=   csr_wr_data;
                    `MTVAL    : csr_mtval     <=   csr_wr_data;
                    `MIP      : csr_mip       <=   csr_wr_data;
                    `MCYCLE   : csr_mcycle    <=   csr_wr_data;
                    `MINSTRET : csr_minstret  <=   csr_wr_data;
                    default:
                    begin
                                csr_mstatus   <=   csr_mstatus;
                                csr_mie       <=   csr_mie;
                                csr_mepc      <=   csr_mepc;
                                csr_mcause    <=   csr_mcause;
                                csr_mtval     <=   csr_mtval;
                                csr_mip       <=   csr_mip;
                                csr_mcycle    <=   csr_mcycle;
                                csr_minstret  <=   csr_minstret;
                    end
                endcase
            end
        else
            begin
                                csr_mstatus   <=   csr_mstatus;
                                csr_mie       <=   csr_mie;
                                csr_mepc      <=   csr_mepc;
                                csr_mcause    <=   csr_mcause;
                                csr_mtval     <=   csr_mtval;
                                csr_mip       <=   csr_mip;
                                csr_mcycle    <=   csr_mcycle + 1'b1;
                                csr_minstret  <=   csr_minstret;
            end
				
		end
	
    always @(*) begin
		if (rst == `RST)
			csr_rd_data = `ZERO_WORD;
		else if (csr_rd_ena == 1'b1)
			case (csr_addr) 
                `MSTATUS  : csr_rd_data   =   csr_mstatus;
                `MIE      : csr_rd_data   =   csr_mie;
                `MEPC     : csr_rd_data   =   csr_mepc;
                `MCAUSE   : csr_rd_data   =   csr_mcause;
                `MTVAL    : csr_rd_data   =   csr_mtval;
                `MIP      : csr_rd_data   =   csr_mip;
                `MCYCLE   : csr_rd_data   =   csr_mcycle;
                `MINSTRET : csr_rd_data   =   csr_minstret;
                default   : csr_rd_data   =   `ZERO_WORD;
            endcase
		else
			csr_rd_data = `ZERO_WORD;
	end

    //为了满足difftest下时钟沿采样的改进，流水线时将会优化掉
        always @(*) begin
		if (rst == `RST)
        begin
            mstatus_o    =  `ZERO_WORD;
            mie_o        =  `ZERO_WORD;
            mepc_o       =  `ZERO_WORD;
            mcause_o     =  `ZERO_WORD;
            mtval_o      =  `ZERO_WORD;
            mip_o        =  `ZERO_WORD;
            mcycle_o     =  `ZERO_WORD;
            minstret_o   =  `ZERO_WORD; 
        end
        else if(csr_wr_ena)
        begin
            case(csr_addr)
                `MSTATUS  : 
                    begin 
                        mstatus_o    =  csr_wr_data;
                        mie_o        =  csr_mie;
                        mepc_o       =  csr_mepc;
                        mcause_o     =  csr_mcause;
                        mtval_o      =  csr_mtval;
                        mip_o        =  csr_mip;
                        mcycle_o     =  csr_mcycle;
                        minstret_o   =  csr_minstret; 
                    end
                `MIE      : 
                    begin 
                        mstatus_o    =  csr_mstatus;
                        mie_o        =  csr_wr_data;
                        mepc_o       =  csr_mepc;
                        mcause_o     =  csr_mcause;
                        mtval_o      =  csr_mtval;
                        mip_o        =  csr_mip;
                        mcycle_o     =  csr_mcycle;
                        minstret_o   =  csr_minstret; 
                    end
                `MEPC     : 
                    begin 
                        mstatus_o    =  csr_mstatus;
                        mie_o        =  csr_mie;
                        mepc_o       =  csr_wr_data;
                        mcause_o     =  csr_mcause;
                        mtval_o      =  csr_mtval;
                        mip_o        =  csr_mip;
                        mcycle_o     =  csr_mcycle;
                        minstret_o   =  csr_minstret; 
                    end
                `MCAUSE   : 
                    begin 
                        mstatus_o    =  csr_mstatus;
                        mie_o        =  csr_mie;
                        mepc_o       =  csr_mepc;
                        mcause_o     =  csr_wr_data;
                        mtval_o      =  csr_mtval;
                        mip_o        =  csr_mip;
                        mcycle_o     =  csr_mcycle;
                        minstret_o   =  csr_minstret; 
                    end
                `MTVAL    : 
                    begin 
                        mstatus_o    =  csr_mstatus;
                        mie_o        =  csr_mie;
                        mepc_o       =  csr_mepc;
                        mcause_o     =  csr_mcause;
                        mtval_o      =  csr_wr_data;
                        mip_o        =  csr_mip;
                        mcycle_o     =  csr_mcycle;
                        minstret_o   =  csr_minstret; 
                    end
                `MIP      :
                    begin 
                        mstatus_o    =  csr_mstatus;
                        mie_o        =  csr_mie;
                        mepc_o       =  csr_mepc;
                        mcause_o     =  csr_mcause;
                        mtval_o      =  csr_mtval;
                        mip_o        =  csr_wr_data;
                        mcycle_o     =  csr_mcycle;
                        minstret_o   =  csr_minstret; 
                    end
                `MCYCLE   : 
                    begin 
                        mstatus_o    =  csr_mstatus;
                        mie_o        =  csr_mie;
                        mepc_o       =  csr_mepc;
                        mcause_o     =  csr_mcause;
                        mtval_o      =  csr_mtval;
                        mip_o        =  csr_mip;
                        mcycle_o     =  csr_wr_data;
                        minstret_o   =  csr_minstret; 
                    end
                `MINSTRET : 
                    begin 
                        mstatus_o    =  csr_mstatus;
                        mie_o        =  csr_mie;
                        mepc_o       =  csr_mepc;
                        mcause_o     =  csr_mcause;
                        mtval_o      =  csr_mtval;
                        mip_o        =  csr_mip;
                        mcycle_o     =  csr_mcycle;
                        minstret_o   =  csr_wr_data; 
                    end
                default   : 
                    begin 
                        mstatus_o    =  mstatus_o;
                        mie_o        =  mie_o;
                        mepc_o       =  mepc_o;
                        mcause_o     =  mcause_o;
                        mtval_o      =  mtval_o;
                        mip_o        =  mip_o;
                        mcycle_o     =  mcycle_o;
                        minstret_o   =  minstret_o; 
         
                    end
            endcase
        end
        else
        begin 
                        mstatus_o    =  mstatus_o;
                        mie_o        =  mie_o;
                        mepc_o       =  mepc_o;
                        mcause_o     =  mcause_o;
                        mtval_o      =  mtval_o;
                        mip_o        =  mip_o;
                        mcycle_o     =  mcycle_o;
                        minstret_o   =  minstret_o; 
        end
    end
       
      

endmodule